`include "top.vh"

module mycpu_top(
    input  wire        aclk,
    input  wire        aresetn,
    output [ 3:0] arid,
    output [31:0] araddr,
    output [ 7:0] arlen,
    output [ 2:0] arsize,
    output [ 1:0] arburst,
    output [ 1:0] arlock,
    output [ 3:0] arcache,
    output [ 2:0] arprot,
    output        arvalid,
    input         arready,
    
    input [ 3:0] rid,
    input [31:0] rdata,
    input [ 1:0] rresp,
    input        rlast,
    input        rvalid,
    output       rready,
    
    output [ 3:0] awid,
    output [31:0] awaddr,
    output [ 7:0] awlen,
    output [ 2:0] awsize,
    output [ 1:0] awburst,
    output [ 1:0] awlock,
    output [ 3:0] awcache,
    output [ 2:0] awprot,
    output        awvalid,
    input         awready,
    
    output [ 3:0] wid,
    output [31:0] wdata,
    output [ 3:0] wstrb,
    output        wlast,
    output        wvalid,
    input         wready,
    
    input [ 3:0] bid,
    input [ 1:0] bresp,
    input        bvalid,
    output       bready,
    // trace debug interface
    output wire [31:0] debug_wb_pc,
    output wire [ 3:0] debug_wb_rf_we,
    output wire [ 4:0] debug_wb_rf_wnum,
    output wire [31:0] debug_wb_rf_wdata
);
wire    reset;
assign  reset = ~aresetn;

wire         ds_allowin;
wire         es_allowin;
wire         ms_allowin;
wire         ws_allowin;

wire         fs_ready_go;
wire         ds_ready_go;
wire         es_ready_go;
wire         ms_ready_go;

wire         fs_to_ds_valid;
wire         ds_to_es_valid;
wire         es_to_ms_valid;
wire         ms_to_ws_valid;

//csr read & write
wire [13:0]  csr_num;
wire [31:0]  csr_rvalue;
wire         csr_we;
wire [31:0]  csr_wvalue;
wire [31:0]  csr_wmask;

//pipeline
wire [`fs_2_ds_bus_wid - 1:0] fs_to_ds_bus;
wire [`ds_2_es_bus_wid - 1:0] ds_to_es_bus;
wire [`es_2_ms_bus_wid - 1:0] es_to_ms_bus;
wire [`ms_2_ws_bus_wid - 1:0] ms_to_ws_bus;
//branch
wire [33:0] br_bus;
//read after write
wire [38:0] es_to_id_bus;
wire [38:0] ms_to_id_bus;
wire [38:0] ws_to_id_bus;
//interrupt
wire has_int;
//ws_ex
wire ms_ex, ws_ex, ws_ex_tlbr;
wire ms_ertn_flush, ws_ertn_flush;
wire [31:0] ex_entry;
wire [31:0] era_entry;
wire [31:0] ex_tlbrentry;
wire [31:0] ws_vaddr;
wire [ 5:0] ws_ecode;
wire [ 8:0] ws_esubcode;
wire fs_ex_tlbr, ex_pif, ex_ipe;
wire es_ex_tlbr, ex_adef, ex_adem, ex_pil, ex_pis, ex_ppi, ex_pme;
//csr data confilct
wire es_read_csr, ms_read_csr, ws_read_csr;

wire         inst_sram_req;
wire         inst_sram_wr;
wire  [ 1:0] inst_sram_size;
wire  [31:0] inst_sram_addr;
wire  [ 3:0] inst_sram_wstrb;
wire  [31:0] inst_sram_wdata;
wire         inst_sram_addr_ok;
wire         inst_sram_data_ok;
wire  [31:0] inst_sram_rdata;
wire         data_sram_req;
wire         data_sram_wr;
wire  [ 1:0] data_sram_size;
wire  [31:0] data_sram_addr;
wire  [ 3:0] data_sram_wstrb;
wire  [31:0] data_sram_wdata;
wire        data_sram_addr_ok;
wire        data_sram_data_ok;
wire [31:0] data_sram_rdata;

wire data_load, data_store;

wire [31:0] inst_addr, data_addr;
wire [31:0] csr_crmd, csr_dmw0, csr_dmw1, csr_asid, csr_tlbehi, csr_tlbidx, csr_tlbelo0, csr_tlbelo1;

wire tlbsrch_valid, tlbrd_valid, tlbwr_valid, tlbfill_valid, invtlb_valid;
wire [88:0] tlbrd_pageinfo;
wire [ 4:0] invtlb_op;
wire [ 9:0] invtlb_asid;
wire [31:0] invtlb_va;
wire        ws_refetch;
wire [31:0] ws_pc;
wire tlbsrch_found;
wire [ 3:0] tlbsrch_index;

// IF stage
if_stage if_stage(
    .clk            (aclk            ),
    .reset          (reset          ),
    //allowin
    .ds_allowin     (ds_allowin     ),
    //brbus
    .br_bus         (br_bus         ),
    //outputs
    .fs_ready_go    (fs_ready_go    ),
    .fs_to_ds_valid (fs_to_ds_valid ),
    .fs_to_ds_bus   (fs_to_ds_bus   ),
    // inst sram interface
    .inst_sram_req  (inst_sram_req  ),
    .inst_sram_wr   (inst_sram_wr   ),
    .inst_sram_wstrb(inst_sram_wstrb),
    .inst_sram_addr (inst_addr      ),
    .inst_sram_wdata(inst_sram_wdata),
    .inst_sram_rdata(inst_sram_rdata),
    .inst_sram_size (inst_sram_size ),
    .inst_sram_addr_ok(inst_sram_addr_ok),
    .inst_sram_data_ok(inst_sram_data_ok),
    //ex
    .ws_ex          (ws_ex          ),
    .ws_ex_tlbr      (ws_ex_tlbr      ),
    .ws_ertn_flush  (ws_ertn_flush  ),
    .ex_adef        (ex_adef        ),
    .ex_tlbr        (fs_ex_tlbr     ),
    .ex_pif         (ex_pif         ),
    .ex_ipe         (ex_ipe         ),
    .ex_entry       (ex_entry       ),
    .era_entry      (era_entry      ),
    .ex_tlbrentry   (ex_tlbrentry   ),
    //refetch
    .ws_refetch     (ws_refetch     ),
    .ws_pc_refetch  (ws_pc          )
);
// ID stage
id_stage id_stage(
    .clk            (aclk           ),
    .reset          (reset          ),
    //allowin
    .es_allowin     (es_allowin     ),
    .ds_allowin     (ds_allowin     ),
    //from fs
    .fs_ready_go    (fs_ready_go    ),
    .fs_to_ds_valid (fs_to_ds_valid ),
    .fs_to_ds_bus   (fs_to_ds_bus   ),
    //from es
    .es_to_id_bus (es_to_id_bus),
    //from ms
    .ms_to_id_bus (ms_to_id_bus),
    //to es
    .ds_ready_go    (ds_ready_go    ),
    .ds_to_es_valid (ds_to_es_valid ),
    .ds_to_es_bus   (ds_to_es_bus   ),
    //to fs
    .br_bus         (br_bus         ),
    //to rf: for write back
    .ws_to_id_bus   (ws_to_id_bus   ),
    //csr data conflict
    .es_ms_ws_read_csr({es_read_csr, ms_read_csr, ws_read_csr}),
    //ex
    .has_int        (has_int        ),
    .ws_ex          (ws_ex          ),
    .ws_ertn_flush     (ws_ertn_flush     ),
    //refetch
    .ws_refetch     (ws_refetch     )
);
// EXE stage
exe_stage exe_stage(
    .clk            (aclk            ),
    .reset          (reset          ),
    //allowin
    .ms_allowin     (ms_allowin     ),
    .es_allowin     (es_allowin     ),
    //from ds
    .ds_ready_go    (ds_ready_go    ),
    .ds_to_es_valid (ds_to_es_valid ),
    .ds_to_es_bus   (ds_to_es_bus   ),
    //to ms
    .es_ready_go    (es_ready_go    ),
    .es_to_ms_valid (es_to_ms_valid ),
    .es_to_ms_bus   (es_to_ms_bus   ),
    //to id
    .es_to_id_bus (es_to_id_bus),
    // data sram interface
    .data_sram_req  (data_sram_req  ),
    .data_sram_wr   (data_sram_wr   ),
    .data_sram_wstrb(data_sram_wstrb),
    .data_sram_addr (data_addr      ),
    .data_sram_wdata(data_sram_wdata),
    .data_sram_size (data_sram_size ),
    .data_sram_addr_ok(data_sram_addr_ok),
    //csr data conflict
    .read_csr       (es_read_csr    ),
    //ex
    .ex_tlbr        (es_ex_tlbr     ),
    .ex_adem        (ex_adem        ),
    .ex_pil         (ex_pil         ),
    .ex_pis         (ex_pis         ),
    .ex_ppi         (ex_ppi         ),
    .ex_pme         (ex_pme         ),
    .ws_ex          (ws_ex          ),
    .ws_ertn_flush  (ws_ertn_flush  ),
    .ms_ex          (ms_ex          ),
    .ms_ertn_flush  (ms_ertn_flush  ),
    //tlb
    .tlbsrch_valid  (tlbsrch_valid  ),
    .invtlb_valid   (invtlb_valid   ),
    .invtlb_op      (invtlb_op      ),
    .invtlb_asid    (invtlb_asid    ),
    .invtlb_va      (invtlb_va      ),

    .data_load      (data_load      ),
    .data_store     (data_store     )
);
// MEM stage
mem_stage mem_stage(
    .clk            (aclk            ),
    .reset          (reset          ),
    //allowin
    .ws_allowin     (ws_allowin     ),
    .ms_allowin     (ms_allowin     ),
    //from es
    .es_ready_go    (es_ready_go    ),
    .es_to_ms_valid (es_to_ms_valid ),
    .es_to_ms_bus   (es_to_ms_bus   ),
    //to ws
    .ms_ready_go    (ms_ready_go    ),
    .ms_to_ws_valid (ms_to_ws_valid ),
    .ms_to_ws_bus   (ms_to_ws_bus   ),
    //to id
    .ms_to_id_bus   (ms_to_id_bus),
    //from data-sram
    .data_sram_rdata(data_sram_rdata),
    .data_sram_data_ok(data_sram_data_ok),
    //csr data conflict
    .read_csr       (ms_read_csr    ),
    //ex input
    .ws_ex          (ws_ex          ),
    .ws_ertn_flush  (ws_ertn_flush     ),
    //ex output
    .ms_ex_out      (ms_ex          ),
    .ms_ertn_flush  (ms_ertn_flush  )
);
// WB stage
wb_stage wb_stage(
    .clk            (aclk            ),
    .reset          (reset          ),
    //allowin
    .ws_allowin     (ws_allowin     ),
    //from ms
    .ms_ready_go    (ms_ready_go    ),
    .ms_to_ws_valid (ms_to_ws_valid ),
    .ms_to_ws_bus   (ms_to_ws_bus   ),
    //to rf: for write back
    .ws_to_id_bus   (ws_to_id_bus   ),
    //trace debug interface
    .debug_wb_pc      (debug_wb_pc      ),
    .debug_wb_rf_we  (debug_wb_rf_we  ),
    .debug_wb_rf_wnum (debug_wb_rf_wnum ),
    .debug_wb_rf_wdata(debug_wb_rf_wdata),
    //csr
    .csr_num        (csr_num        ),
    .csr_we_out     (csr_we         ),
    .csr_rvalue     (csr_rvalue     ),
    .csr_wvalue     (csr_wvalue     ),
    .csr_wmask      (csr_wmask      ),
    //csr data conflict
    .read_csr       (ws_read_csr    ),
    //ex
    .ws_ex_out      (ws_ex          ),
    .ws_ex_tlbr     (ws_ex_tlbr     ),
    .ws_ertn_flush     (ws_ertn_flush     ),
    .Ecode          (ws_ecode       ),
    .EsubCode       (ws_esubcode    ),
    .ws_vaddr       (ws_vaddr       ),
    //tlb
    .tlbrd_valid          (tlbrd_valid          ),
    .tlbwr_valid          (tlbwr_valid          ),
    .tlbfill_valid        (tlbfill_valid        ),
    // refetch
    .ws_pc          (ws_pc          ),
    .ws_refetch     (ws_refetch     )
);

//csr
csr csr(
    .clk            (aclk            ),
    .reset          (reset          ),
//sent by ws
    //csr read & write
    .csr_num        (csr_num        ),
    .csr_we         (csr_we         ),
    .csr_wvalue     (csr_wvalue     ),
    .csr_wmask      (csr_wmask      ),
//send to ws
    //csr read
    .csr_rvalue     (csr_rvalue     ),
//ex
    .ex_entry       (ex_entry       ),
    .ex_tlbrentry   (ex_tlbrentry   ),
    .ws_ex          (ws_ex          ),
    .ws_pc          (ws_pc          ),
    .ws_ecode       (ws_ecode       ),
    .ws_esubcode    (ws_esubcode    ),
    
    .ertn_flush     (ws_ertn_flush  ),
    .era_entry      (era_entry      ),
    .has_int        (has_int        ),
    .ws_vaddr       (ws_vaddr       ),
//tlb
    .csr_crmd       (csr_crmd       ),
    .csr_dmw0       (csr_dmw0       ),
    .csr_dmw1       (csr_dmw1       ),
    .csr_asid       (csr_asid       ),
    .csr_tlbehi     (csr_tlbehi     ),
    .tlbsrch_valid  (tlbsrch_valid  ),
    .tlbsrch_found  (tlbsrch_found  ),
    .tlbsrch_index  (tlbsrch_index  ),
    .tlbrd_valid     (tlbrd_valid   ),
    .csr_tlbidx     (csr_tlbidx     ),
    .csr_tlbelo0    (csr_tlbelo0    ),
    .csr_tlbelo1    (csr_tlbelo1    ),
    .tlbrd_pageinfo (tlbrd_pageinfo )
);

SRAM_2_AXI_bridge SRAM_2_AXI_bridge(
    .aclk           (aclk      ),
    .aresetn        (aresetn),

    .arid           (arid      ),
    .araddr         (araddr    ),
    .arlen          (arlen     ),
    .arsize         (arsize    ),
    .arburst        (arburst   ),
    .arlock         (arlock    ),
    .arcache        (arcache   ),
    .arprot         (arprot    ),
    .arvalid        (arvalid   ),
    .arready        (arready   ),
    
    .rid            (rid       ),
    .rdata          (rdata     ),
    .rresp          (rresp     ),
    .rlast          (rlast     ),
    .rvalid         (rvalid    ),
    .rready         (rready    ),
    
    .awid           (awid      ),
    .awaddr         (awaddr    ),
    .awlen          (awlen     ),
    .awsize         (awsize    ),
    .awburst        (awburst   ),
    .awlock         (awlock    ),
    .awcache        (awcache   ),
    .awprot         (awprot    ),
    .awvalid        (awvalid   ),
    .awready        (awready   ),
    
    .wid            (wid       ),
    .wdata          (wdata     ),
    .wstrb          (wstrb     ),
    .wlast          (wlast     ),
    .wvalid         (wvalid    ),
    .wready         (wready    ),
    
    .bid            (bid       ),
    .bresp          (bresp     ),
    .bvalid         (bvalid    ),
    .bready         (bready    ),
    
    .inst_sram_req     (inst_sram_req    ),
    .inst_sram_wr      (inst_sram_wr     ),
    .inst_sram_size    (inst_sram_size   ),
    .inst_sram_addr    (inst_sram_addr   ),
    .inst_sram_wstrb   (inst_sram_wstrb  ),
    .inst_sram_wdata   (inst_sram_wdata  ),
    .inst_sram_addr_ok (inst_sram_addr_ok),
    .inst_sram_data_ok (inst_sram_data_ok),
    .inst_sram_rdata   (inst_sram_rdata  ),
    .data_sram_req     (data_sram_req    ),
    .data_sram_wr      (data_sram_wr     ),
    .data_sram_size    (data_sram_size   ),
    .data_sram_addr    (data_sram_addr   ),
    .data_sram_wstrb   (data_sram_wstrb  ),
    .data_sram_wdata   (data_sram_wdata  ),
    .data_sram_addr_ok (data_sram_addr_ok),
    .data_sram_data_ok (data_sram_data_ok),
    .data_sram_rdata   (data_sram_rdata  )
);

mmu mmu(
    .clk                (aclk),
    .resetn             (aresetn),
    .inst_addr          (inst_addr),
    .data_addr          (data_addr),
    .inst_sram_addr     (inst_sram_addr),
    .data_sram_addr     (data_sram_addr),
// from csr
    .csr_crmd           (csr_crmd),
    .csr_dmw0           (csr_dmw0),
    .csr_dmw1           (csr_dmw1),
    .csr_asid           (csr_asid),
    .csr_tlbehi         (csr_tlbehi),
    .csr_tlbidx         (csr_tlbidx),
    .csr_tlbelo0        (csr_tlbelo0),
    .csr_tlbelo1        (csr_tlbelo1),
// tlb inst  
    .tlbsrch_valid      (tlbsrch_valid),
    .tlbrd_valid        (tlbrd_valid),
    .tlbwr_valid        (tlbwr_valid),
    .tlbfill_valid      (tlbfill_valid),
    .invtlb_valid       (invtlb_valid),
// tlbrd_valid
    .tlbrd_pageinfo     (tlbrd_pageinfo),
// invtlb
    .invtlb_op          (invtlb_op),
    .invtlb_asid        (invtlb_asid),
    .invtlb_va          (invtlb_va),
// tlbsrch
    .tlbsrch_found      (tlbsrch_found),
    .tlbsrch_index      (tlbsrch_index),

    .fs_ex_tlbr         (fs_ex_tlbr),
    .ex_adef            (ex_adef),
    .ex_pif             (ex_pif),
    .ex_ipe             (ex_ipe),
    .es_ex_tlbr         (es_ex_tlbr),
    .ex_adem            (ex_adem),
    .ex_pil             (ex_pil),
    .ex_pis             (ex_pis),
    .ex_ppi             (ex_ppi),
    .ex_pme             (ex_pme),

    .data_load          (data_load),
    .data_store         (data_store)
);

endmodule